#include "vl_buffer.h"
#include <cstring>
#include <list>
#if defined __VL_BUFFER_FEATURE_APPLE || defined __VL_BUFFER_FEATURE_UNIX
#include <unistd.h>
#endif

using namespace VL;

namespace VL {

/**
 * @brief: CimZzz
 * @date: 2023-11-22 11:21:30
 * 
 * 内存缓冲区最小扩容单位
 */
constexpr const size_t VLBUFFER_MIN_EXPAND_UNIT = 64;
constexpr const size_t VLBUFFER_SOURCE_READ_BUFFER_SIZE = 1024;

constexpr const char _vlbuffer_print_digits_lower_case[] = "0123456789abcdefghijklmnopqrstuvwxyz";
constexpr const char _vlbuffer_print_digits_upper_case[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

struct _vlbuffer_find_matcher {
	vlbyte_cp mbs;
	size_t mbs_len;
	size_t idx;
	size_t k;
	size_t next_arr_idx;
	_vlbuffer_find_matcher* next_item;
};

class _vlbuffer_inner_istream_source: public vlbuffer_source {
public:
	explicit _vlbuffer_inner_istream_source(std::istream& in): in(in) {}

	virtual size_t fetch(vlbyte_p sink, size_t offset, size_t len) override {
		return in.read(((char *) sink + offset), len).gcount();
	}
	virtual bool can_read() override {
		return in.operator bool();
	}
private:
	std::istream& in;
};


#if defined __VL_BUFFER_FEATURE_APPLE || defined __VL_BUFFER_FEATURE_UNIX
class _vlbuffer_inner_fd_source: public vlbuffer_source {
public:
	explicit _vlbuffer_inner_fd_source(int fd): fd(fd), eof(false) {}

	virtual size_t fetch(vlbyte_p sink, size_t offset, size_t len) override {
		ssize_t read_len = ::read(this->fd, sink + offset, len);
		if(read_len < 0) {
			throw vlbuffer_exception("read fd occur error: %ld", read_len);
		}
		if(read_len == 0) {
			this->eof = true;
			return 0;
		}
		return read_len;
	}
	virtual bool can_read() override {
		return !eof && this->fd >= 0;
	}
private:
	int fd;
	bool eof;
};
#endif

VLBUFFER_INLINE void _vlbuffer_multi_bytes_copy(vlbyte_p dest, vlbyte_cp src, size_t src_len, size_t nitems) {
	while(nitems > 0) {
		std::memcpy((void*) dest, (void*) src, src_len);
		dest += src_len;
		nitems --;
	}
}

VLBUFFER_INLINE void _vlbuffer_setup_next_arr(vlbyte_cp mbs, size_t mbs_len, size_t* next_arr) {
	next_arr[0] = 0;
	if(mbs_len == 1) {
		return;
	}
	size_t k = 0, i = 1;
	while(i < mbs_len) {
		if(mbs[i] == mbs[k]) {
			next_arr[i] = k + 1;
			i ++;
			k ++;
		} else if(k > 0) {
			k = next_arr[k - 1];
		} else {
			next_arr[i] = 0;
			i ++;
		}
	}
}

}

vlbuffer_exception::vlbuffer_exception(const char * msg, ...): msg() {
	va_list va, va_cp;
	va_start(va, msg);
	va_copy(va_cp, va);
	size_t len = ::vsnprintf(nullptr, 0, msg, va_cp);
	va_end(va_cp);
	char buf[len + 1];
	buf[len] = '\0';
	::vsnprintf(buf, len + 1, msg, va);
	va_end(va);
	this->msg = buf;
}
const char* vlbuffer_exception::what() const _NOEXCEPT {
	return msg.c_str();
}

vlbuffer_find_matcher::vlbuffer_find_matcher(char c): vlbuffer_find_matcher((vlbyte) c) {}
vlbuffer_find_matcher::vlbuffer_find_matcher(const char* str): vlbuffer_find_matcher((vlbyte_cp) str, std::strlen(str)) {}
vlbuffer_find_matcher::vlbuffer_find_matcher(const char* str, size_t len): vlbuffer_find_matcher((vlbyte_cp) str, len) {}

vlbuffer_base::~vlbuffer_base() {}
void vlbuffer_base::fill_byte(vlbyte byte, size_t offset, size_t nitems) {
	this->check_cap(offset + nitems);
	std::memset((void*) (this->_buf + offset), byte, nitems);
}
void vlbuffer_base::fill_mbs(vlbyte_cp bytes, size_t len, size_t offset, size_t nitems) {
	if(len == 1) {
		this->fill_byte(*bytes, offset, nitems);
		return;
	}
	size_t fill_len = len * nitems;
	this->check_cap(offset + fill_len);
	vlbyte_p begin = this->_buf + offset;
	_vlbuffer_multi_bytes_copy(begin, bytes, len, nitems);
}
void vlbuffer_base::copy_from(vlbyte_cp from, size_t offset, size_t len) {
	this->check_cap(offset + len);
	vlbyte_p begin = this->_buf + offset;
	std::memcpy((void *) begin, (void *) from, len);
}
void vlbuffer_base::copy_to(vlbyte_p to, size_t offset, size_t len) const {
	if(len == 0) return;
	size_t require_len = offset + len;
	VLBUFFER_ERROR_CHECK(require_len > this->_total_len, "exceed buffer range. total is %zu, but require is %zu", this->_total_len, require_len)
	std::memcpy(to, this->_buf + offset, len);
}
vlbuffer_position vlbuffer_base::find(const vlbuffer_find_matcher& matcher, size_t offset, size_t len) const {
	vlbuffer_position position = {
		.is_found = false,
		.begin_idx = 0,
		.end_idx = 0
	};
	if(matcher.mbs == nullptr || matcher.mbs_len == 0) return position;
	if(matcher.mbs_len == 1) {
		vlbyte search_byte = matcher.mbs[0];
		if(offset >= this->_total_len) return position;
		if(len == 0) {
			// 从 offset 位置一直找到末尾
			len = this->_total_len - offset;
		} else {
			if(offset + len > this->_total_len) {
				len = this->_total_len - offset;
			}
		}
		vlbyte_cp ptr = this->_buf + offset;
		while(len > 0) {
			if(*ptr == search_byte) {
				position.is_found = true;
				position.begin_idx = offset;
				position.end_idx = offset + 1;
				break;
			}
			offset ++;
			ptr ++;
			len --;
		}
	} else {
		vlbyte_cp search_mbs = matcher.mbs;
		size_t search_len = matcher.mbs_len;
		if(offset + search_len > this->_total_len) return position;
		if(len == 0 || offset + len > this->_total_len) {
			// 从 offset 位置一直找到末尾
			len = this->_total_len - offset;
		}

		// 使用 KMP 算法
		// 首先初始化 next_arr
		size_t next_arr[search_len]; // 无需初始化 
		_vlbuffer_setup_next_arr(search_mbs, search_len, next_arr);
		// 开始查找
		vlbyte_cp ptr = this->_buf + offset;
		size_t k = 0;
		while (len > 0) {
			if(search_mbs[k] == *ptr) {
				k++;
				if(k == search_len) {
					// found
					position.is_found = true;
					position.begin_idx = offset - search_len + 1;
					position.end_idx = offset + 1;
					break;
				}
			} else if(k > 0) {
				k = next_arr[k - 1];
				continue;
			}
			ptr ++;
			offset ++;
			len --;
		}
	}
	return position;
}
vlbuffer_multi_position vlbuffer_base::find_multi(const std::vector<vlbuffer_find_matcher>& search_mbs_arr, size_t offset, size_t len) const {
	vlbuffer_multi_position position = {
		.is_found = false,
		.found_mbs = nullptr,
		.found_idx = 0,
		.begin_idx = 0,
		.end_idx = 0
	};
	size_t total_match_item_size = search_mbs_arr.size();
	if(total_match_item_size == 0) return position;
	if(offset >= this->_total_len) return position;
	if(len == 0 || offset + len > this->_total_len) {
		// 从 offset 位置一直找到末尾
		len = this->_total_len - offset;
	}
	size_t counter = 0;
	size_t total_next_arr_len = 0;
	size_t effect_count = 0;
	_vlbuffer_find_matcher* match_head = nullptr, * pending_head = nullptr, * tmp = nullptr;
	_vlbuffer_find_matcher filter_match_arr[total_match_item_size];
	for(auto & search_item : search_mbs_arr) {
		if(search_item.mbs_len > len || search_item.mbs_len == 0 || search_item.mbs == nullptr) {
			counter ++;
			continue;
		}
		filter_match_arr[effect_count] = {
			.mbs = search_item.mbs,
			.mbs_len = search_item.mbs_len,
			.idx = counter,
			.k = 0,
			.next_arr_idx = total_next_arr_len,
			.next_item = nullptr
		};
		if(match_head == nullptr) 
			match_head = &filter_match_arr[effect_count];
		else {
			filter_match_arr[effect_count].next_item = match_head;
			match_head = &filter_match_arr[effect_count];
		}
		total_next_arr_len += search_item.mbs_len;
		counter ++;
		effect_count ++;
	}
	// 如果长度都超过字节缓冲区总长度的话, 返回未找到
	if(total_next_arr_len == 0) return position;
	// 初始化 next 数组
	size_t next_arr[total_next_arr_len];
	std::memset((void *) next_arr, 0, sizeof(size_t) * total_next_arr_len);
	tmp = match_head;
	while(tmp != nullptr) {
		size_t next_arr_idx = tmp->next_arr_idx;
		vlbyte_cp mbs = tmp->mbs;
		size_t mbs_len = tmp->mbs_len;
		_vlbuffer_setup_next_arr(mbs, mbs_len, next_arr + next_arr_idx);
		tmp = tmp->next_item;
	}
	// 开始查找
	vlbyte_cp ptr = this->_buf + offset;
	while(len > 0) {
		tmp = match_head;
		vlbyte b = *ptr;
		while(tmp != nullptr) {
			if(b == tmp->mbs[tmp->k]) {
				tmp->k ++;
				if(tmp->k == tmp->mbs_len) {
					position.is_found = true;
					position.found_mbs = tmp->mbs;
					position.found_idx = tmp->idx;
					position.begin_idx = offset - tmp->mbs_len + 1;
					position.end_idx = offset + 1;
					break;
				}
			} else if(tmp->k > 0) {
				tmp->k = next_arr[tmp->k - 1 + tmp->next_arr_idx];
				continue;
			}
			tmp = tmp->next_item;
		}
		if(position.is_found) break;
		ptr ++;
		offset ++;
		len --;
	}
	return position;
}

vlbuffer_position vlbuffer_base::start_with(const vlbuffer_find_matcher& matcher, size_t offset) const {
	vlbuffer_position position = {
		.is_found = false,
		.begin_idx = 0,
		.end_idx = 0
	};
	if(matcher.mbs == nullptr || matcher.mbs_len == 0) return position;
	if(offset >= this->_total_len) return position;
	vlbyte_cp search_mbs = matcher.mbs;
	size_t search_len = matcher.mbs_len;

	vlbyte_cp begin = this->_buf + offset;
	for(size_t i = 0 ; i < search_len ; i ++, begin ++) {
		if(search_mbs[i] != *begin) {
			return position;
		}
	}
	position.is_found = true;
	position.begin_idx = offset;
	position.end_idx = offset + search_len;
	return position;
}
vlbuffer_multi_position vlbuffer_base::start_with_multi(const std::vector<vlbuffer_find_matcher>& search_mbs_arr, size_t offset) const {
	vlbuffer_multi_position position = {
		.is_found = false,
		.found_mbs = nullptr,
		.found_idx = 0,
		.begin_idx = 0,
		.end_idx = 0
	};
	size_t total_match_item_size = search_mbs_arr.size();
	if(total_match_item_size == 0) return position;
	if(offset >= this->_total_len) return position;
	
	_vlbuffer_find_matcher* match_head = nullptr, * pending_head = nullptr, * tmp = nullptr, * parent = nullptr;
	_vlbuffer_find_matcher filter_match_arr[total_match_item_size];
	size_t counter = 0;
	size_t effect_count = 0;
	for(auto & search_item : search_mbs_arr) {
		if(search_item.mbs_len + offset >= this->_total_len || search_item.mbs_len == 0 || search_item.mbs == nullptr) {
			counter ++;
			continue;
		}
		filter_match_arr[effect_count] = {
			.mbs = search_item.mbs,
			.mbs_len = search_item.mbs_len,
			.idx = counter,
			.k = 0,
			.next_arr_idx = 0,
			.next_item = nullptr
		};
		if(match_head == nullptr) 
			match_head = &filter_match_arr[effect_count];
		else {
			filter_match_arr[effect_count].next_item = match_head;
			match_head = &filter_match_arr[effect_count];
		}
		counter ++;
		effect_count ++;
	}
	if(match_head == nullptr) return position;
	vlbyte_cp begin = this->_buf + offset;
	for(size_t i = 0 ; ; i ++, begin ++) {
		tmp = match_head;
		parent = nullptr;
		while(tmp != nullptr) {
			if(tmp->mbs[i] != *begin) {
				// 不匹配, 移除
				if(tmp == match_head) {
					match_head = match_head->next_item;
					tmp = match_head;
				} else {
					parent->next_item = tmp->next_item;
					tmp = tmp->next_item;
				}
				continue;
			}
			if(i + 1 == tmp->mbs_len) {
				// found
				position.is_found = true;
				position.found_idx = tmp->idx;
				position.found_mbs = tmp->mbs;
				position.begin_idx = offset;
				position.end_idx = offset + tmp->mbs_len;
				return position;
			}
			parent = tmp;
			tmp = tmp->next_item;
		}
	}

	return position;
}

void vlbuffer_base::append(const char * str, size_t offset, size_t len) {
	if(str == nullptr) return;
	if(len == 0) {
		size_t str_len = std::strlen(str);
		if(offset == str_len) return;
		VLBUFFER_ERROR_CHECK(offset >= str_len, "offset is over when append char*. offset is %zu, but total of char* is %zu", offset, str_len);
		len = str_len - offset;
		this->copy_from((vlbyte_cp)(str + offset), this->_write_idx, len);
		this->_write_idx += len;
	} else {
		this->copy_from((vlbyte_cp)(str + offset), this->_write_idx, len);
		this->_write_idx += len;
	}
}
void vlbuffer_base::append(const std::string& str, size_t offset, size_t len) {
	if(len == 0) {
		size_t str_len = str.length();
		if(offset == str_len) return;
		VLBUFFER_ERROR_CHECK(offset >= str_len, "offset is over when append std::string. offset is %zu, but total of std::string is %zu", offset, str_len);
		len = str_len - offset;
		this->copy_from((vlbyte_cp)(str.c_str() + offset), this->_write_idx, len);
		this->_write_idx += len;
	} else {
		this->copy_from((vlbyte_cp)(str.c_str() + offset), this->_write_idx, len);
		this->_write_idx += len;
	}
}
void vlbuffer_base::append(const vlbuffer_base& buf, size_t offset, size_t len) {
	if(len == 0) {
		size_t buf_len = buf._total_len;
		if(offset == buf_len) return;
		VLBUFFER_ERROR_CHECK(offset >= buf_len, "offset is over when append buffer. offset is %zu, but total of buffer is %zu", offset, buf_len);
		len = buf_len - offset;
		this->copy_from(buf._buf + offset, this->_write_idx, len);
		this->_write_idx += len;
	} else {
		size_t require_len = offset + len;
		VLBUFFER_ERROR_CHECK(require_len > buf._total_len, "copied buffer is not enough capacity. total is %zu, but require is %zu", buf._total_len, require_len);
		this->copy_from(buf._buf + offset, this->_write_idx, len);
		this->_write_idx += len;
	}
}

size_t vlbuffer_base::append(vlbuffer_source& source, size_t read_len, size_t read_buf_size) {
	if(!source.can_read()) return 0;
	size_t total_read = 0, src_read_len = 0, already_read_len = 0, need_read_len = 0, idx = this->_write_idx;
	if(read_len == 0) {
		// 一直读到 EOF
		if(read_buf_size == 0) {
			// source 读取缓冲区
			read_buf_size = VLBUFFER_SOURCE_READ_BUFFER_SIZE;
		}
		vlbyte read_buf[read_buf_size];
		need_read_len = read_buf_size;
		while(source.can_read()) {
			src_read_len = source.fetch(read_buf, already_read_len, need_read_len);
			VLBUFFER_ERROR_CHECK(src_read_len > need_read_len, "invalid size read from vlbuffer_source. require read length is %zu, but inform read size is %zu", need_read_len, src_read_len);
			if(already_read_len + src_read_len < read_buf_size) {
				// 读取长度不足读取缓冲区长度时, 暂不追加至字节缓冲区, 再次进行读取
				already_read_len += src_read_len;
				need_read_len = read_buf_size - already_read_len;
				continue;
			}
			this->copy_from(read_buf, idx, read_buf_size);
			total_read += read_buf_size;
			idx += read_buf_size;
			already_read_len = 0;
			need_read_len = read_buf_size;
		}
		if(already_read_len != 0) {
			this->copy_from(read_buf, idx, already_read_len);
			total_read += already_read_len;
			idx += already_read_len;
		}
		this->_write_idx = idx;
	} else {
		// 读到 read_len 或 eof 为止
		if(read_buf_size != 0) {
			if(read_buf_size > read_len) {
				read_buf_size = read_len;
			}
		} else if(read_len < VLBUFFER_SOURCE_READ_BUFFER_SIZE) {
			read_buf_size = read_len;
		} else {
			read_buf_size = VLBUFFER_SOURCE_READ_BUFFER_SIZE;
		}
		vlbyte read_buf[read_buf_size];
		need_read_len = read_buf_size;

		while(source.can_read() && read_len > 0) {
			src_read_len = source.fetch(read_buf, already_read_len, need_read_len);
			VLBUFFER_ERROR_CHECK(src_read_len > need_read_len, "invalid size read from vlbuffer_source. require read length is %zu, but inform read size is %zu", need_read_len, src_read_len);
			if(already_read_len + src_read_len < read_buf_size) {
				// 读取长度不足读取缓冲区长度时, 暂不追加至字节缓冲区, 再次进行读取
				already_read_len += src_read_len;
				need_read_len = read_buf_size - already_read_len;
				continue;
			}
			this->copy_from(read_buf, idx, read_buf_size);
			total_read += read_buf_size;
			idx += read_buf_size;

			read_len -= read_buf_size;
			if(read_len < read_buf_size) {
				read_buf_size = read_len;
			}
			already_read_len = 0;
			need_read_len = read_buf_size;
		}
		if(already_read_len != 0) {
			this->copy_from(read_buf, idx, already_read_len);
			total_read += already_read_len;
			idx += already_read_len;
		}
		this->_write_idx = idx;
	}

	return total_read;
}
size_t vlbuffer_base::append_until(vlbuffer_source& source, const vlbuffer_find_matcher& matcher, size_t read_len, size_t read_buf_size) {
	if(!source.can_read()) return 0;
	if(matcher.mbs == nullptr || matcher.mbs_len == 0) return this->append(source, read_len, read_buf_size);
	size_t total_read = 0, read_buf_idx = 0, idx = this->_write_idx;
	if(matcher.mbs_len == 1) {
		// 单字节模式
		vlbyte search_byte = matcher.mbs[0];
		if(read_len == 0) {
			if(read_buf_size == 0) {
				read_buf_size = read_len < VLBUFFER_SOURCE_READ_BUFFER_SIZE ? read_len : VLBUFFER_SOURCE_READ_BUFFER_SIZE;
			}

			vlbyte read_buf[read_buf_size];
			
			while(source.can_read()) {
				int byte = source.fetch_one_byte();
				if(byte < 0) break;
				read_buf[read_buf_idx ++] = byte;
				if(byte == search_byte) {
					break;
				}
				if(read_buf_idx == read_buf_size) {
					this->copy_from(read_buf, idx, read_buf_size);
					total_read += read_buf_size;
					idx += read_buf_size;

					read_buf_idx = 0;
				}
			}

			if(read_buf_idx > 0) {
				this->copy_from(read_buf, idx, read_buf_idx);
				total_read += read_buf_idx;
				idx += read_buf_idx;
			}
			this->_write_idx = idx;
		} else {
			if(read_buf_size != 0) {
				if(read_buf_size > read_len) {
					read_buf_size = read_len;
				}
			} else if(read_len < VLBUFFER_SOURCE_READ_BUFFER_SIZE) {
				read_buf_size = read_len;
			} else {
				read_buf_size = VLBUFFER_SOURCE_READ_BUFFER_SIZE;
			}
			vlbyte read_buf[read_buf_size];
			while(source.can_read() && read_len > 0) {
				int byte = source.fetch_one_byte();
				if(byte < 0) break;
				read_buf[read_buf_idx ++] = byte;
				if(byte == search_byte) {
					break;
				}
				read_len --;
				if(read_buf_idx == read_buf_size) {
					this->copy_from(read_buf, idx, read_buf_size);
					total_read += read_buf_size;
					idx += read_buf_size;

					read_buf_idx = 0;
				}
			}
			if(read_buf_idx > 0) {
				this->copy_from(read_buf, idx, read_buf_idx);
				total_read += read_buf_idx;
				idx += read_buf_idx;
			}
			this->_write_idx = idx;
		}
	} else {
		// 使用 KMP 算法
		vlbyte_cp search_mbs = matcher.mbs;
		size_t search_len = matcher.mbs_len;
		int byte;
		// 首先初始化 next_arr
		size_t next_arr[search_len]; // 无需初始化 
		_vlbuffer_setup_next_arr(search_mbs, search_len, next_arr);
		size_t k = 0;
		if(read_len == 0) {
			// 一直读到 EOF
			if(read_buf_size == 0) {
				// source 读取缓冲区
				read_buf_size = VLBUFFER_SOURCE_READ_BUFFER_SIZE;
			}
			vlbyte read_buf[read_buf_size];
			bool is_skip_read = false;
			while(source.can_read()) {
				if(is_skip_read) {
					is_skip_read = false;
				} else {
					byte = source.fetch_one_byte();
					if(byte < 0) break;
					read_buf[read_buf_idx ++] = byte;
				}
				if(search_mbs[k] == byte) {
					k ++;
					if(k == search_len) {
						break;
					}
				} else if(k > 0) {
					k = next_arr[k - 1];
					is_skip_read = true;
					continue;
				}
				if(read_buf_idx == read_buf_size) {
					this->copy_from(read_buf, idx, read_buf_size);
					total_read += read_buf_size;
					idx += read_buf_size;
					read_buf_idx = 0;
				}
			}
			if(read_buf_idx > 0) {
				this->copy_from(read_buf, idx, read_buf_idx);
				total_read += read_buf_idx;
				idx += read_buf_idx;
			}
			this->_write_idx = idx;
		} else {
			// 读到 read_len 或 eof 为止
			if(read_buf_size != 0) {
				if(read_buf_size > read_len) {
					read_buf_size = read_len;
				}
			} else if(read_len < VLBUFFER_SOURCE_READ_BUFFER_SIZE) {
				read_buf_size = read_len;
			} else {
				read_buf_size = VLBUFFER_SOURCE_READ_BUFFER_SIZE;
			}
			vlbyte read_buf[read_buf_size];

			bool is_skip_read = false;
			while(source.can_read() && read_len > 0) {
				if(is_skip_read) {
					is_skip_read = false;
				} else {
					byte = source.fetch_one_byte();
					if(byte < 0) break;
					read_buf[read_buf_idx ++] = byte;
					read_len --;
				}
				if(search_mbs[k] == byte) {
					k ++;
					if(k == search_len) {
						break;
					}
				} else if(k > 0) {
					k = next_arr[k - 1];
					is_skip_read = true;
					continue;
				}
				if(read_buf_idx == read_buf_size) {
					this->copy_from(read_buf, idx, read_buf_size);
					total_read += read_buf_size;
					idx += read_buf_size;
					read_buf_idx = 0;
				}
			}
			if(read_buf_idx > 0) {
				this->copy_from(read_buf, idx, read_buf_idx);
				total_read += read_buf_idx;
				idx += read_buf_idx;
			}
			this->_write_idx = idx;
		}
	}
	return total_read;
}
size_t vlbuffer_base::append(std::istream& in, size_t read_len, size_t read_buf_size) {
	if(!in) return 0;
	_vlbuffer_inner_istream_source in_source(in);
	return this->append(in_source, read_len, read_buf_size);
}
size_t vlbuffer_base::append_until(std::istream& in, const vlbuffer_find_matcher& matcher, size_t read_len, size_t read_buf_size) {
	if(!in) return 0;
	_vlbuffer_inner_istream_source in_source(in);
	return this->append_until(in_source, matcher, read_len, read_buf_size);
}
#if defined __VL_BUFFER_FEATURE_APPLE || defined __VL_BUFFER_FEATURE_UNIX
size_t vlbuffer_base::append_fd(int fd, size_t read_len, size_t read_buf_size) {
	if(fd < 0) return 0;
	_vlbuffer_inner_fd_source fd_source(fd);
	return this->append(fd_source, read_len, read_buf_size);
}
size_t vlbuffer_base::append_fd_until(int fd, const vlbuffer_find_matcher& matcher, size_t read_len, size_t read_buf_size) {
	if(fd < 0) return 0;
	_vlbuffer_inner_fd_source fd_source(fd);
	return this->append_until(fd_source, matcher, read_len, read_buf_size);
}
#endif
void vlbuffer_base::print(std::ostream& stream, const vlbuffer_print_option& options) const {
	// 先检查打印范围
	size_t offset = options.offset;
	size_t len = options.len;
	if(len == 0) {
		len = this->_total_len;
		VLBUFFER_ERROR_CHECK(offset > len, "the specified length exceeds capacity of buffer. offset: %zu, len: %zu, capacity: %zu", offset, len, this->_total_len)
		if(offset == len) return;
		len = len - offset;
	} else {
		VLBUFFER_ERROR_CHECK(offset > len || offset + len > this->_total_len, "the specified length exceeds capacity of buffer. offset: %zu, len: %zu, capacity: %zu", offset, len, this->_total_len)
	} 
	vlbyte_cp begin = this->_buf + offset;
	unsigned char radix = options.radix;
	VLBUFFER_ERROR_CHECK(radix < 2 || radix > 36, "radix must between 2 and 36. now radix: %u", radix)
	const char * prefix = options.prefix;
	if(options.flag & vlbuffer_print_option::PRINT_ADDRESS) {
		prefix = nullptr;
	}
	else if(prefix == nullptr) {
		switch(radix) {
			case 2:
				prefix = "0b";
				break;
			case 8:
				prefix = "0";
				break;
			case 16:
				prefix = "0x";
				break;
			case 24:
				prefix = "0t";
				break;
			case 36:
				prefix = "0k";
				break;
		}
	}

	unsigned char keep_count = 0;
	if(options.flag & vlbuffer_print_option::PRINT_UNIFY) {
		if(radix == 2) {
			keep_count = 8;
		} else if(radix == 3) {
			keep_count = 6;
		} else if(radix <= 6) {
			keep_count = 4;
		} else if (radix <= 15) {
			keep_count = 3;
		} else {
			keep_count = 2;
		}
	}

	const char* digits;
	if(options.flag & vlbuffer_print_option::PRINT_UPPER_CASE) {
		digits = _vlbuffer_print_digits_upper_case;
	} else {
		digits = _vlbuffer_print_digits_lower_case;
	}

	bool show_address = options.flag & vlbuffer_print_option::PRINT_ADDRESS;
	bool show_proc_address = (options.flag & vlbuffer_print_option::PRINT_PROC_ADDRESS) == vlbuffer_print_option::PRINT_PROC_ADDRESS;
	size_t begin_address = show_proc_address ? (size_t)begin : offset;

	// 开始打印
	char print_buf[16]{0};
	int i, j;
	size_t print_count = 0;
	const char* calc_print_buf;
	while(len -- > 0) {
		vlbyte byte = *begin;
		
		if(options.break_count > 0 && print_count == options.break_count) {
			stream << '\n';
			print_count = 0;
			begin_address += options.break_count;
		}

		if(print_count == 0 && show_address) {
			size_t address = begin_address;
			for(i = 14; i >= 14 - sizeof(size_t) ; i --) {
				if(address != 0) {
					print_buf[i] = digits[address % radix];
					address /= 16;
				} else {
					print_buf[i] = '0';
				}
			}
			stream << "0x" << (const char *)(print_buf + i + 1);
		}
		// 进制转换
		for(i = 14, j = 0; byte != 0 ; byte /= radix, i --, j ++) {
			print_buf[i] = digits[byte % radix];
		}
		if(keep_count > 0 && j < keep_count) {
			unsigned char fill_count = keep_count - j;
			std::memset(print_buf + i + 1 - fill_count, options.unify_code, fill_count);
			i -= fill_count;
		}
		calc_print_buf = &print_buf[i + 1];

		if(prefix == nullptr) {
			if(print_count != 0 && options.separator != nullptr) {
				stream << options.separator << calc_print_buf;
			} else {
				stream << calc_print_buf;
			}
		} else {
			if(print_count != 0 && options.separator != nullptr) {
				stream << options.separator << prefix << calc_print_buf;
			} else {
				stream << prefix << calc_print_buf;
			}
		}
		begin ++;
		print_count ++;
	}

	stream << '\n';
}


vlbuffer_reader vlbuffer_reader_core::reader() const {
	return vlbuffer_reader(this->_base_buf);
}
void vlbuffer_reader_core::read_until(vlbuffer_base& dest, const vlbuffer_find_matcher& matcher) {
	vlbuffer_position pos = this->_base_buf.find(matcher, this->_read_idx);
	if(pos.begin_idx == pos.end_idx) {
		return;
	}
	// 有合适区间
	dest.append(this->_base_buf, this->_read_idx, pos.end_idx - this->_read_idx);
	this->_read_idx = pos.end_idx;
}

vlbuffer::vlbuffer(): vlbuffer_base(), vlbuffer_reader_core(*dynamic_cast<vlbuffer_base *>(this)) {}
vlbuffer::vlbuffer(size_t init_cap): vlbuffer_base(), vlbuffer_reader_core(*dynamic_cast<vlbuffer_base *>(this)) {
	this->check_cap(init_cap);
}
vlbuffer::vlbuffer(const vlbuffer& buf): vlbuffer_base(), vlbuffer_reader_core(*dynamic_cast<vlbuffer_base *>(this)) {
	this->append(buf);
}
vlbuffer::vlbuffer(vlbuffer&& buf): vlbuffer_base(), vlbuffer_reader_core(*dynamic_cast<vlbuffer_base *>(this)) {
	this->_buf = buf._buf;
	this->_total_len = buf._total_len;
	this->_write_idx = buf._write_idx;
	this->_read_idx = buf._read_idx;
	buf._buf = nullptr;
	buf._total_len = 0;
	buf._read_idx = 0;
	buf._write_idx = 0;
}
vlbuffer::vlbuffer(const vlbuffer_base& buf): vlbuffer_base(), vlbuffer_reader_core(*dynamic_cast<vlbuffer_base *>(this)) {
	this->append(buf);
}
vlbuffer::~vlbuffer() {
	if(this->_buf != nullptr) {
		std::free(this->_buf);
		this->_total_len = 0;
		this->_write_idx = 0;
		this->_read_idx = 0;
		this->_buf = nullptr;
	}
}
void vlbuffer::operator=(const vlbuffer& buf) {
	this->release();
	this->append(buf);
}
void vlbuffer::operator=(vlbuffer&& buf) {
	this->release();
	this->_buf = buf._buf;
	this->_total_len = buf._total_len;
	this->_write_idx = buf._write_idx;
	this->_read_idx = buf._read_idx;
	buf._buf = nullptr;
	buf._total_len = 0;
	buf._read_idx = 0;
	buf._write_idx = 0;
}
void vlbuffer::operator=(const vlbuffer_base& buf) {
	this->release();
	this->append(buf);
}
void vlbuffer::reset() {
	this->_write_idx = 0;
	this->_read_idx = 0;
}
void vlbuffer::release() {
	if(this->_buf != nullptr) {
		std::free(this->_buf);
		this->_total_len = 0;
		this->_buf = nullptr;
	}
	this->reset();
}
void vlbuffer::expand_cap(size_t cap) {
	if(cap == 0) return;
	size_t need_expansion_remainder = cap % VLBUFFER_MIN_EXPAND_UNIT;
	size_t real_expansion_size;
	if(need_expansion_remainder == 0) {
		real_expansion_size = cap;
	} else {
		real_expansion_size = cap + VLBUFFER_MIN_EXPAND_UNIT - need_expansion_remainder;
	}
	// 对实际扩容尺寸取整(以 __VL_BUFFER_MIN_EXPAND_UNIT 为整)
	if(this->_buf == nullptr) {
		// 申请内存空间
		this->_buf = (vlbyte_p)std::malloc(real_expansion_size);
		VLBUFFER_ERROR_CHECK(this->_buf == nullptr, "cannot alloc memory")
	} else {
		vlbyte_p tmp_ptr = (vlbyte_p)std::realloc((void*) this->_buf, this->_total_len + real_expansion_size);
		VLBUFFER_ERROR_CHECK(tmp_ptr == nullptr, "cannot realloc more memory")
		this->_buf = tmp_ptr;
	} 
	this->_total_len += real_expansion_size;
}